/**
 * Created by 009 on .p.
 */
(function ($, window, document, undefined) {

    "use strict";
    window = (typeof window != 'undefined' && window.Math == Math)
        ? window
        : (typeof self != 'undefined' && self.Math == Math)
            ? self
            : Function('return this')()
    ;
    $.fn.tablebind = function (tableColumns, tableSettings) {
        var
            settings = ( $.isPlainObject(tableSettings) )
                ? $.extend(true, {}, $.fn.tablebind.settings, tableSettings)
                : $.extend({}, $.fn.tablebind.settings),
            columns = ($.isArray(tableColumns))
                ? tableColumns
                : [],
            customOpItems = ($.isArray(settings.customOpItems))
                ? settings.customOpItems
                : $.fn.tablebind.settings.customOpItems,
            lengthList = ( $.isPlainObject(tableSettings) )
                ? ($.isArray(tableSettings.lengthList)
                    ? tableSettings.lengthList
                    : $.fn.tablebind.settings.lengthList)
                : $.fn.tablebind.settings.lengthList,
            _lengthList,
            $wrapper = ($(this).length === 0)
                ? $('<div></div>')
                : $(this),
            $table_section = $wrapper.children('div:has(table)'),
            key = settings.key,
            _columns = [],
            $toolbar = $(this).find('div[data-section=toolBar]'),
            $table = $table_section.find('table'),
            $view_add = $(this).find('div[data-section=add]'),
            table_id = queryTableId(settings.tableId),
            $view_update = $('.modal[data-section=update][data-table='+table_id+']'),
            $view_delete = $('.modal[data-section=delete][data-table='+table_id+']'),
            module;

        initNS();

        mergeColumns();

        initLengthList();

        reviseOpItems();


        module = {
            initialize : function () {
                if($table_section.length === 0) {
                    $table_section = $('<div></div>');
                    $wrapper.prepend($table_section);
                    $table_section.data('section', 'table');
                    $table_section.attr('data-section', 'table');
                    $table_section.addClass('overflowX');

                } else if ($table_section.attr('data-section') != 'table') {
                    $table_section.data('section', 'table');
                    $table_section.attr('data-section', 'table');
                }
                if($toolbar.length === 0) {
                    $toolbar = createToolBar();
                    $table_section.prepend($toolbar);
                    $toolbar.find('.ui.calendar').calendar();
                    $toolbar.find('.ui.dropdown').dropdown();
                }
                if($table.length === 0) {
                    $table = createTable();
                    $table_section.append($table);
                    $table.find('.ui.dropdown').dropdown();
                    $table.data('total', 0);
                    $table.data('size', 0);
                } else if($table.find('tfoot').length === 0) {
                    var $footer = createPagingBar();
                    $table.append($footer);
                    module.loadPaging($table, $table.data('total'), 1, $table.data('size'));
                    $table.find('.ui.dropdown').dropdown();
                }
                if(($view_add.length === 0) && (settings.enableAdd === true)) {
                    $view_add = createAddView();
                    $wrapper.append($view_add);
                    $view_add.find('.ui.calendar').calendar();
                    $view_add.find('.ui.dropdown').dropdown();
                }
                //load update view
                if(($view_update.length === 0) && settings.enableEdit === true) {
                    $view_update = createUpdateView();
                    $('body').append($view_update);
                    $view_update.modal({closable : false, observeChanges : true});//init
                    $view_update.find('.ui.calendar').calendar();
                    $view_update.find('.ui.dropdown').dropdown();
                }

                if(($view_delete.length === 0) && settings.enableDelete === true) {
                    $view_delete = createDeleteView();
                    $('body').append($view_delete);
                    $view_delete.modal({
                        observeChanges : true,
                        onDeny    : function(){
                            return false;
                        },
                        onApprove : function() {
                            return false;
                        }
                    });

                }

                /*if((!(settings.customOpItems === undefined)) &&
                    (!(settings.customOpItems.length === 0))) {
                    $.each(settings.customOpItems, function (idx, item) {
                        createCommonOpView(item);
                    });
                }*/

                //
                module.bindEvents.toolbar();
                module.bindEvents.tablerow();
                module.bindEvents.pagingall();


                //
                if(settings.autoLoad) {
                    retriveTable();
                }
            },
            //
            bindEvents : {

                toolbar : function () {
                    $toolbar.find('button').on('click', function () {
                        $table_section.slideToggle('slow');
                        $view_add.slideToggle('slow');
                    });

                    $toolbar.find('div[name=import]').off('click');
                    $toolbar.find('div[name=import]').children('i.dropdown.icon').click(function () {
                        $toolbar.find('div[name=import]').dropdown('toggle');
                    });
                    $toolbar.find('div[name=import]').children('span').click(function () {
                        $toolbar.find('form[name=excel]').find('input[name=file]').click();
                    });
                    $toolbar.find('div[name=import]').find('.item').eq(0).click(function () {
                        $toolbar.find('form[name=excel]').find('input[name=file]').click();
                    });
                    $toolbar.find('div[name=import]').find('.item').eq(1).click(function () {
                        //download template file
                        window.open(settings.importTemplateUrl);
                    });
                    $toolbar.find('form[name=excel]').find('input[name=file]').on('change', function () {
                        console.info('starting import.....');
                        var dat = new FormData($toolbar.find('form[name=excel]')[0]);
                        importData(dat);
                    });
                },
                rowedit : function (tr) {
                    var tools = $(tr).find('td:last'),
                        _edit = tools.find('button:has(.edit.icon)');
                    _edit.click(function () {
                        var data = obtainRowData(tr);
                        var id = $(tr).data('id');
                        stuffForm($view_update.find('form'), data);
                        $view_update.find('input[type=hidden][data-name=id]').val(id);
                        $view_update.modal({
                            closable : false,
                            observeChanges : true,
                            onHidden : function () {
                                module.get.onEditHide();
                            }});
                        $view_update.modal('resize');
                        $view_update.modal('show');
                    });
                },
                rowdelete : function (tr) {
                    var tools = $(tr).find('td:last'),
                        _del = tools.find('button:has(.delete.icon)');
                    _del.click(function () {
                        var id = $(tr).data('id');
                        $view_delete.find('input[type=hidden][data-name=id]').val(id);
                        $view_delete.modal('show');
                    });
                },
                rowdbclick : function (tr) {
                    $(tr).on('dblclick', function () {
                        var tools = $(tr).find('td:last'),
                            _edit = tools.find('button:has(.edit.icon)');
                        _edit.click();
                    });
                },
                rowOpItems : function (tr) {
                    var tools = $(tr).find('td:last'),
                        items = tools.find('[data-item=op]');
                    $.each(customOpItems, function (i, item) {
                        var op = items[i];
                        if(op === undefined) return true;
                        var req_data = obtainRowData(tr);
                        var key = module.get.setting.key;
                        req_data[key] = $(tr).data(key);
                        var _req_data = {};
                        _req_data = item.extraData;
                            $.each(item.data, function (i) {
                            var name = item.date[i];
                            _req_data[name] = req_data[name];
                        });



                         $(op).click(function () {
                         if(item.confirmEnable === true) {
                         var $confirm = createCommonOpView();
                         $('body').append($confirm);
                         $confirm.children('.header').text(item.confirmHeader);
                         $confirm.children('.content').text(item.confirmText);
                         var btn = $confirm.children('.actions').find('.positive.button');
                         $confirm.modal('show');

                         btn.click(function () {
                         $confirm.modal('hide');
                         $confirm.remove();
                         module.get.loader.process().dimmer('show');
                             var headers = module.get.tokens();
                             setTimeout(function () {
                                 $.ajax({
                                     url: item.url,
                                     method: item.method,
                                     dataType : 'json',
                                     contentType: 'application/json',
                                     headers : headers,
                                     data: _req_data
                                 }).done(function () {
                                     module.get.loader.success().dimmer('show');
                                     //
                                     setTimeout(function () {
                                         retriveTable();
                                     },300);

                                 })
                                     .fail(function (data) {
                                         module.get.loader.fail('操作失败', JSON.stringify(data)).dimmer('show');
                                     })
                                     .always(function () {
                                         //module.get.loader.process().dimmer('hide');
                                     });
                             },300);

                         });
                         } else {
                             module.get.loader.process().dimmer('show');
                             setTimeout(function () {
                                 $.ajax({
                                     url: item.url,
                                     method: item.method,
                                     dataType : 'json',
                                     contentType: 'application/json',
                                     data: _req_data
                                 }).done(function () {
                                     module.get.loader.success().dimmer('show');
                                     //
                                     setTimeout(function () {
                                         retriveTable();
                                     },300);

                                 })
                                     .fail(function (data) {
                                         module.get.loader.fail('操作失败', JSON.stringify(data)).dimmer('show');
                                     })
                                     .always(function () {
                                         //module.get.loader.process().dimmer('hide');
                                     });
                             }, 300)
                         }

                         });
                    });
                },
                tablerow : function () {
                    var editable = module.get.setting.editable(),
                        deletable = module.get.setting.deletable();
                    $table.children('tbody').children('tr').each(function (idx, tr) {
                        if(editable) {
                            module.bindEvents.rowedit(tr);
                        }
                        if(deletable) {
                            module.bindEvents.rowdelete(tr);
                        }

                        if(settings.dbClickEditable === true) {
                            module.bindEvents.rowdbclick(tr);
                        }

                        if(customOpItems.length > 0) {
                            module.bindEvents.rowOpItems(tr);
                        }
                    });
                },

                paging : function () {
                    $table.children('tfoot').find('.ui.pagination.menu a:not(.disabled):not(.icon):not(.active)').each(function (idx, a) {
                        $(a).click(function () {
                            var page = module.get.page(),
                                e_page = parseInt($(this).text());
                            page = isNaN(e_page)?page:e_page;
                            var queryData = module.get.query();
                            queryData.page = page;
                            retriveTable(queryData);
                        });
                    });
                    $table.children('tfoot').find('.ui.pagination.menu a.icon:not(.disabled)').each(function (idx, a) {
                        $(a).click(function () {
                            var page = module.get.page();
                            if($(a).hasClass('left')) {
                                page = page - 1;
                            } else if ($(a).hasClass('right')) {
                                page = page + 1;
                            }
                            page = (page < 1)?module.get.page():page;
                            var queryData = module.get.query();
                            queryData.page = page;
                            retriveTable(queryData);
                        });
                    });
                },
                pagingsize : function () {
                    $table.children('tfoot').find('.ui.pagination.label select')
                        .off('change.databind')
                        .on('change.databind', function () {
                            retriveTable();
                        });
                },
                pagejump : function () {
                    $table.children('tfoot').find('.ui.pagination.label button.jump')
                        .off('click.databind')
                        .on('click.databind', function () {
                            var page = module.get.page(),
                                jpage = $table
                                    .children('tfoot').find('.ui.pagination.label .ui.input.jump')
                                    .children('input').val();
                            page = (isNaN(parseInt(jpage))) ? page : parseInt(jpage);
                            page = (page < 1)?module.get.page():page;
                            $table
                                .children('tfoot').find('.ui.pagination.label .ui.input.jump')
                                .children('input').val(page);
                            var queryData = module.get.query();
                            queryData.page = page;
                            retriveTable(queryData);
                        });
                    $table.children('tfoot').find('.ui.pagination.label .ui.input.jump').children('input')
                        .off('keyup.databind')
                        .on('keyup.databind', function(event){
                            if(event.keyCode === 13) {
                                $table
                                    .children('tfoot')
                                    .find('.ui.pagination.label button.jump')
                                    .click();
                            }
                        });
                    $table.children('tfoot').find('.ui.pagination.label .ui.input.jump').children('input')
                        .off('input.databind propertychange.databind')
                        .on('input.databind propertychange.databind', function (e) {
                            var val = $(e.target).val();
                            if(isNaN(parseInt(val)) ||(parseInt(val) <= 0)) {
                                $(e.target).val('');
                            }
                        });
                },
                pagingall : function () {
                    module.bindEvents.paging();
                    module.bindEvents.pagejump();
                    module.bindEvents.pagingsize();
                }
            },

            refresh : function (data) {
                var $tbody = $table.children('tbody');

                var total = data.total,
                    page = data.page,
                    page_size = data.pageSize;

                var editable = module.get.setting.editable(),
                    deletable = module.get.setting.deletable();

                var editItem = editable
                        ? ('<button class="ui mini teal labeled icon button"><i class="edit icon"></i>编辑</button>')
                        : (''),
                    deleItem = deletable
                        ? ('<button class="ui mini red labeled icon button"><i class="delete icon"></i>删除</button>')
                        : ('');
                var opItems = '';
                $.each(customOpItems, function (i, item) {
                    var $ui = $('<div></div>');
                    $ui.html(item.ui);
                    $ui.children().attr('data-item','op');
                    opItems += $ui.html();
                });


                $tbody.empty();
                $.each(data.rows, function (idx_row, row) {
                    var $tr = $('<tr></tr>');
                    //attach key to data id
                    $tr.data('id', row[key]);
                    $tr.attr('data-id', row[key]);
                    //add row no
                    $tr.append('<td>'+((page-1)*page_size + (idx_row+1))+'</td>');
                    $.each(columns, function (idx_col, col) {
                        var $td = $('<td></td>'),
                            inner = $.fn.tablebind.component.output.write[col.type](row[col.name], col.options, col.optionValues);
                        if(col.type === 'reference') {
                            //
                            inner = $.fn.tablebind.component.output.write[col.type](row[col.name], row[col.textName]);
                        }
                        $td.data('name', col.name);
                        $td.attr('data-name', col.name);
                        $td.html(inner);
                        $tr.append($td);
                    });

                    $tr.append('<td data-name="tools">' +
                        '<div>' +
                        editItem +
                        deleItem +
                            opItems +
                        '</div>' +
                        '</td>');
                    $tbody.append($tr);
                });
                module.bindEvents.tablerow();

                module.loadPaging($table, total, page, page_size);
                module.bindEvents.paging();


            },

            loadPaging : function loadPaging(table, total, current_page, page_size) {
                var $table = $(table);
                var total_page = Math.ceil(total / page_size);
                var $label_bar = $table.find('.pagination.label'),
                    $menu_bar = $table.find('.pagination.menu'),
                    $page_labels = $label_bar.children('strong');

                $page_labels.eq(0).text(total);
                $page_labels.eq(1).text(total_page);

                var $pre = $('<a class="icon item left"><i class="left chevron icon"></i>上一页</a>'),
                    $next = $('<a class="icon item right">下一页<i class="right chevron icon"></i></a>'),
                    $items = $('<div></div>');
                if(total_page < 7) {
                    var start = 0;
                    while (start < total_page) {
                        start ++;
                        if(start === current_page) {
                            $items.append('<a class="item active">'+start+'</a>');
                        }
                        else {
                            $items.append('<a class="item">'+start+'</a>');
                        }
                    }
                } else if(current_page < 5) {
                    var start = 0;
                    while (start < 5) {
                        start ++;
                        if(current_page === start) {
                            $items.append('<a class="item active">'+start+'</a>');
                        } else {
                            $items.append('<a class="item">'+start+'</a>');
                        }
                    }
                    $items.append('<a class="item disabled">...</a>');
                    $items.append('<a class="item">'+total_page+'</a>');

                } else if((total_page - current_page) < 4) {
                    $items.append('<a class="item">1</a>');
                    $items.append('<a class="item disabled">...</a>');

                    var start = total_page - 4;
                    while (start <= total_page) {
                        if(start === current_page) {
                            $items.append('<a class="item active">'+start+'</a>');
                        } else {
                            $items.append('<a class="item">'+start+'</a>');
                        }
                        start ++;
                    }
                } else {
                    $items.append('<a class="item">1</a>');
                    $items.append('<a class="item disabled">...</a>');
                    $items.append('<a class="item">'+(current_page-1)+'</a>');
                    $items.append('<a class="item active">'+(current_page)+'</a>');
                    $items.append('<a class="item">'+(current_page+1)+'</a>');
                    $items.append('<a class="item disabled">...</a>');
                    $items.append('<a class="item">'+total_page+'</a>');
                }
                //
                if(current_page === 1) {
                    $pre.addClass('disabled');
                }
                if(current_page === total_page) {
                    $next.addClass('disabled')
                }
                $menu_bar.html($pre).append($items.html()).append($next);
            },

            get : {
                page : function () {
                    var $current_item = $table.children('tfoot').find('.pagination.menu a.active'),
                        page = 1;
                    page = ($current_item.length === 0) ? page : $current_item.text();
                    page = parseInt(page);
                    if(isNaN(page)) page = 1;
                    return page;
                },
                size : function () {
                    var $page_size_selector = $table.find('.pagination.label').find('select'),
                        size = module.get.pageLength;
                    size = ($page_size_selector.length === 0) ? size : $page_size_selector.val();
                    size = parseInt(size);
                    if(isNaN(size)) size = module.get.pageLength;
                    return size;
                },
                column : function (name) {
                    var column;
                    $.each(columns, function (idx, col) {
                        if(name === col.name) {
                            column = col;
                            return false;
                        }
                    });
                    return column;
                },
                tokens : function () {
                    var headers = {};
                    var token = $("meta[name='_csrf']").attr("content"),
                        header = $("meta[name='_csrf_header']").attr("content");
                    headers[header] = token;
                    return headers;
                },
                loader : {
                    process : function () {
                        const info = '请求处理中...';
                        var _info = arguments.length > 0 ? arguments[0] : info;
                        var $dimmer = $('body').children('.ui.page.inverted.dimmer');
                        if($dimmer.length === 0) {
                            $dimmer = $('<div class="ui page inverted dimmer"></div>');
                            $('body').append($dimmer);
                        }
                        $dimmer.html('');
                        $dimmer.append('<div class="content"><div class="center"><div class="ui large text loader"><h2></h2></div></div></div>');
                        $dimmer.find('.ui.loader h2').text(_info);
                        $dimmer.dimmer({closable : false});

                        return $dimmer;
                    },
                    success : function () {
                        const info = '操作成功';
                        var _info = arguments.length > 0 ? arguments[0] : info;
                        var $dimmer = $('body').children('.ui.page.inverted.dimmer');
                        if($dimmer.length === 0) {
                            $dimmer = $('<div class="ui page inverted dimmer"></div>');
                            $('body').append($dimmer);
                        }
                        $dimmer.html('');
                        $dimmer.append('<div class="content"><div class="center"> <h2 class="ui icon header green"><i class="check circle icon green"></i><span></span></h2> </div></div>');
                        $dimmer.find('.ui.green span').text(_info);
                        $dimmer.dimmer({closable : true});

                        return $dimmer;
                    },
                    fail : function () {
                        const info = '操作失败';
                        var _info = arguments.length > 0 ? arguments[0] : info,
                            err = arguments.length > 1 ? arguments[1] : undefined;
                        var $dimmer = $('body').children('.ui.page.inverted.dimmer');
                        if($dimmer.length === 0) {
                            $dimmer = $('<div class="ui page inverted dimmer"></div>');
                            $('body').append($dimmer);
                        }
                        $dimmer.html('');
                        $dimmer.append('<div class="content"><div class="center"> <h2 class="ui icon header red"><i class="remove circle icon red"></i><span></span></h2> </div></div>');
                        $dimmer.find('.ui.red span').text(_info);
                        if(!(err === undefined)) {
                            var $msg = $('<div class="ui error message"></div>');
                            $msg.text(err);
                            $dimmer.find('.center').append($msg);
                        }

                        $dimmer.dimmer({closable : true});

                        return $dimmer;
                    }

                },
                setting : {
                    editable : function () {
                        return (settings.enableEdit === true)?true:false;
                    },
                    deletable : function () {
                        return (settings.enableDelete === true)?true:false;
                    },
                    key : settings.key
                },
                pageLength : _lengthList[0],
                onEditHide : function () {

                },
                query : function () {
                    var obj = {
                        page : module.get.page(),
                        size : module.get.size()
                    };
                    if($toolbar.length === 0) return obj;
                    var name = $toolbar.find('.ui.search.dropdown.selection select').val(),
                        val = $toolbar.find('.ui.action.input input').val();
                    if((name === undefined) || (val === undefined)
                        || (name === null) || (val === null)
                        || (name.trim() === '') || (val.trim() === '')) {
                        return obj;
                    }
                    obj[name]=val;
                    return obj;
                }

            }
        };

        function initNS() {
            $wrapper.data('id', table_id);
            settings.tableId = table_id;
        }

        function initLengthList() {
            _lengthList = numberList(lengthList);
            _lengthList = (_lengthList.length === 0)
                ? $.fn.tablebind.settings.lengthList
                : _lengthList;

            settings.lengthList  = _lengthList;
        }

        function reviseOpItems() {
            $.each(customOpItems, function (i,item) {
                item = $.extend(true,{},$.fn.tablebind.columnOpItem,item);
                customOpItems[i] = item;
            });
            //reset
            settings.customOpItems = customOpItems;
        }
        function mergeColumns() {
            $.each(columns, function (idx,col) {
                col = $.isPlainObject(col)
                    ? $.extend(true, {}, $.fn.tablebind.column, col)
                    : $.extend({}, $.fn.tablebind.column, {label:idx,name:idx});
                col.index = idx;
                _columns.push(col);
            });
            columns = _columns;
        }

        function clearForm(form) {
            $.each(columns, function (idx, col) {
                var colname = col.name,
                    coltype = col.type;
                var $field  = $(form).find('input[name='+colname+']');
                if($field.length === 0) return true;
                $.fn.tablebind.component.input.write.reset[coltype]($field);
            });
        }

        function stuffForm(form, data) {
            $.each(columns, function (idx, col) {
                if(!(col.updatable === true)) return true;
                var colname = col.name,
                    coltype = col.type;
                var $field  = $(form).find('.field:has([name='+colname+'])');
                if($field.length === 0) return true;
                $.fn.tablebind.component.input.write.reset[coltype]($field);
                $.fn.tablebind.component.input.write.val[coltype]($field, data[colname]);
            });
        }

        function queryTableId(tableId) {
            if(tableId === undefined) {
                return 'data_table_' + $('table').length
            }
            return tableId;
        }

        function settingException(msg) {
            this.message = msg;
            this.name = 'settingException';
        }

        function sortNumber(a, b) {
            return a - b;
        }

        function obtainRowData(tr) {
            var row_data = {};
            $(tr).find('td:not(:first):not(:last)').each(function (idx, td) {

                var name = $(td).data('name');
                var column = module.get.column(name);
                if(column === undefined) return true;
                var value = $.fn.tablebind.component.output.retrieve[column.type]($(td),
                    column.options,
                    column.optionValues);
                row_data[name]=value;
            });
            //
            return row_data;
        }

        function createImportItem() {
            var $import = $('<div class="ui labeled icon dropdown button" name="import"><span>Excel导入</span>' +
                '<i class="dropdown icon"></i><div class="menu">' +
                '<div class="item"><span class="text">导入数据</span></div>' +
                '<div class="item"><span class="text">下载模板</span></div>' +

 '</div></div><form name="excel" style="display: none;" enctype ="multipart/form-data">' +
                '<input name="file" accept=".csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" type="file"></form>');
            return $import;
        }

        function createAddItem() {
            var $add = $('<button class="ui green labeled icon button"><i class="add icon"></i>添加</button>');
            return $add;
        }

        function createSearchItem() {
            var $search = $('<div class="nine wide column row">' +
                '<div><span>选择列：</span><select class="ui search dropdown"></select></div>' +
                '<div>' +
                '<div class="ui action left icon input"><i class="search icon"></i><input type="text" placeholder="搜索...">' +
                '<div class="ui blue button">查询</div></div></div>');
            var options = '';
            $.each(columns, function () {
                options += this.searchable?'<option value="'+this.name+'">'+this.label+'</option>':'';
            });
            $search.find('select').html($search.find('select').html()+options);

            $search.find('.ui.button').click(function () {
                var $si = $search.find('.ui.action.input input');
                var words = $si.val();
                console.info(words);
                $si.val(words.trim());
                //reset page as first page when do search
                var queryData = module.get.query();
                queryData.page = 1;
                retriveTable(queryData);
            });
            $search.find('input').on('keyup', function (event) {
                if(event.keyCode === 13) {
                    $search.find('.ui.button').click();
                }
            });

            return $search;
        }

        function createToolBar() {
            var $tool = $('<div class="ui grid segment" data-section="toolBar"></div>'),
                $tool_left = $('<div></div>'),
                $add = $(''),
                $import = $(''),
                $search = createSearchItem();
            if(settings.enableAdd === true) {
                $add = createAddItem();
                $tool_left.append($add);
            }
            if(settings.enableImport === true) {
                $import = createImportItem();
                $tool_left.append($import);
            }
            var children = $tool_left.children();
            if(children.length === 1) {
                $tool_left.addClass('two wide column ');
            } else if(children.length >= 2) {
                $tool_left.addClass('three wide column ');
            }
            $tool.append($tool_left).append($search);
            //
            return $tool;
        }

        function createTable() {
            var $table = $('<table class="ui small celled striped selectable compact table"><thead><tr></tr></thead><tbody></tbody></table>'),
                $head = $table.children('thead').children('tr');

            $head.append('<th>#</th>');
            $.each(columns, function () {
                $head.append('<th>'+this.label+'</th>');
            });
            $head.append('<th class="two wide">操作</th>');

            var $foot = createPagingBar();
            $table.append($foot);
            return $table;
        }

        function createPagingBar() {
            var $footer = $('<tfoot><tr></tr></tfoot>');

            $footer.children('tr').append('<th colspan="'+(columns.length+2)+'">' +
                '<div class="ui pagination label floated left">' +
                '<strong>0</strong><span class="section">条</span>' +
                '<strong>0</strong><span class="section">页</span>' +
                '<span>每页</span><span class="section"></span>' +
                '<select name="pagesize" class="ui mini dropdown">' +
                createOptions() +
                '</select>' +
                '<span class="section"></span><span>条</span>' +
                '<span class="section"></span>' +
                '<div class="ui input jump">' +
                '<input placeholder="跳页" size="4" maxlength="4" type="text">' +
                '</div>' +
                '<span class="section"></span>' +
                '<button class="ui tiny primary button jump">确定</button>' +
                '</div>' +
                '<div class="ui mini right floated pagination menu "></div></th>');
            return $footer;
        }

        function createOptions() {
            var options = '';
            $.each(_lengthList, function (idx, len) {
                var selected = (idx === 0)?('selected="selected"'):'';
                options += '<option value="'+len+'" '+selected+'>'+len+'</option>';
            });
            return options;
        }

        function createAddView() {
            var $view = $('<div class="segment" style="display: none;"></div>');
            $view.attr('data-section', 'add');

            var $form_container = $('<div class="ui segment"><div class="ui huge header">添加数据</div><div class="content"></div></div>'),
                $form_footer = messageForm(),
                $form = $('<form class="ui form"></form>');
            messageHide($form_footer);
            $form_container.append($form_footer);
            $form.append('<div class="ui divider"></div>');
            $.each(columns, function (idx, col) {
                if(!col.writable) return true;
                var $field = $($.fn.tablebind.component.input.write.inline[col.type]);
                $field
                    .append($.fn.tablebind.component.input.write.label['text'](col.label))
                    .append($.fn.tablebind.component.input.write.input[col.type]);
                $.fn.tablebind.component.input.write.name[col.type]($field, col.name);
                $.fn.tablebind.component.input.write.tip[col.type]($field, col.tip);
                $.fn.tablebind.component.input.write.values(col.type, $field, col.options, col.optionValues);
                if(col.required === true) $field.addClass('required');
                if($.fn.tablebind.component.input.bind[col.type] === undefined);
                else {
                    $.fn.tablebind.component.input.bind[col.type]($field, col.ref);
                }
                //
                $form.append($field);
            });
            var $actions = $('<div class="actions">' +
                '<div class="ui button">取消</div>' +
                '<div class="ui primary button">保存</div>' +
                '</div>');
            $form.append('<div class="ui divider"></div>').append($actions)
                .append('<div class="ui error message"></div>');
            $form_container.find('.content').append($form);
            $view.append($form_container);

            $actions.children('.ui.button').eq(0).click(function () {
                $table_section.slideToggle('slow');
                $view.slideToggle('slow');
            });

            $actions.children('.ui.button').eq(1).click(function (event) {
                $form.find('.ui.error.message').html('');
                messageInfo($form_footer)
                if(settings.addUrl === '') {
                    return;
                }
                disableForm($form);
                setTimeout(function () {
                    $form.form('validate form')
                }, 500);
            });

       //form validate rules

            var fields = {},fieldIds = [],fieldCols={};
            $.each(columns, function (idx, col) {
                if (!col.writable) return true;
                fields[col.name] = {
                    identifier : col.name,
                    rules : col.validate
                }
                fieldIds.push(col.name);
                fieldCols[col.name] = col;
            });

            $form.form({
                fields : fields,
                onSuccess : function (event, fields) {
                    //filt some empty value non-update
                    $.each(fieldIds, function (idx, name) {
                        var col = fieldCols[name];
                        var fieldValue = fields[name];
                        if(!(fieldValue === '') || !(fieldValue.trim() === '')) return true;
                        if(((col.type === 'image') || (col.type === 'file') || (col.type === 'reference'))) {
                            delete fields[name];
                        } else if((col.emptyIsNull === true)) {
                            delete fields[name];
                        }
                    });
                    var headers = module.get.tokens();
                    //post data
                    $.ajax({
                        type : 'POST',
                        url : settings.addUrl,
                        data : JSON.stringify(fields),
                        contentType : "application/json",
                        dataType : 'json',
                        headers : headers,
                        success: function (data){
                            if(data.code === 1) {
                                $.each(data.data, function (id, error) {
                                    $form.form('add prompt', id);
                                    console.log(error);
                                });
                                $form.form('add errors', data.data);

                            } else {
                                messageSuccess($form_footer);
                                settings.onAddSucess($view, $wrapper, table_id);
                                setTimeout(function () {
                                    location.reload();
                                }, 500);
                            }

                        }
                    }).done(function (data) {
                    }).fail(function (data) {
                        console.info('fail');
                        console.info(JSON.stringify(data));
                        messageFail($form_footer, JSON.stringify(data), $view);
                        settings.onAddFail(data, $view, $wrapper, table_id);
                    }).always(function () {
                        if($form_footer.hasClass('info')) {
                            messageHide($form_footer);
                        }
                        enableForm($form);
                    });
                },
                //保留
                onFailure : function (formErrors, fields) {
                    messageHide($form_footer);
                    enableForm($form);
                }

            });

            return $view;
        }

        function messageSuccess($message, info) {
            $message.removeClass('info').removeClass('error').addClass('success');
            messageClear($message);
            $message.append('<div class="header">操作成功</div>');
            if(!(info === undefined)) {
                var $info = $('<p></p>');
                $info.text(info);
                $message.append($info);
            }
            messageShow($message);
        }

        function messageFail($message, info, $view) {
            $message.removeClass('info').removeClass('success').addClass('error');
            messageClear($message);
            $message.append('<div class="header">操作失败</div>');
            if(!(info === undefined)) {
                var $info = $('<p></p>');
                $info.text(info);
                $message.append($info);
            }
            messageShow($message);
            if($view.attr('data-section') === 'update')
            $view.modal('refresh');
        }

        function messageInfo($message) {
            $message.removeClass('error').removeClass('success').addClass('info');
            messageClear($message);
            $message.append('<div class="header"></div>')
                .append('<div class="icon label">请求处理中 ...  &nbsp;&nbsp;<i class="icon spinner loading"></i></div>');
            messageShow($message);
        }

        function messageHide($message) {
            $message.addClass('hidden');
        }

        function messageShow ($message) {
            $message.removeClass('hidden');
        }

        function messageClear($message) {
            $message.html('');
        }

        function messageForm() {
            var $form_footer = $('<div class="ui hidden message footer"></div>');
            return $form_footer;
        }

        function numberList(numbers) {
            var _numbers = [];
            if(!Array.isArray(numbers)) return _numbers;

            $.each(numbers,
                function(idx, num) {
                    var _num = parseInt(num);
                    if (!isNaN(_num) && ($.inArray(num, _numbers) === -1)) _numbers.push(_num);
                });
            _numbers.sort(sortNumber);
            return _numbers;
        }

        function disableForm(form) {
            $(form).find('div.field').each(function () {
                $(this).addClass('disabled');
            });
            $(form).find('.actions .button').each(function () {
                $(this).addClass('disabled');
            });
        }

        function enableForm(form) {
            $(form).find('div.field').each(function () {
                $(this).removeClass('disabled');
            });
            $(form).find('.actions .button').each(function () {
                $(this).removeClass('disabled');
            });
        }

        function createUpdateView() {
            var $view = $('<div class="ui modal segment"></div>');
            $view.attr('data-section', 'update');
            $view.attr('data-table', table_id);

            $view.html('<i class="close icon massive"></i><div class="header">编辑</div>');
            var $content = $('<div class="content"><form class="ui form"></form></div>'),
                $form_footer = messageForm(),
                $actions = $('<div class="actions">' +
                    '<div class="ui button">取消</div>' +
                    '<div class="ui primary button">保存</div>'),
                $key = $('<input type="hidden" data-name="id">'),
                $form = $content.children('form');
            $key.data('name', 'id');
            $form.append($key);

            messageHide($form_footer);

            $.each(columns, function (idx, col) {
                if(!col.updatable) return true;
                var $field = $($.fn.tablebind.component.input.write.inline[col.type]);
                $field
                    .append($.fn.tablebind.component.input.write.label['text'](col.label))
                    .append($.fn.tablebind.component.input.write.input[col.type]);
                $.fn.tablebind.component.input.write.name[col.type]($field, col.name);
                $.fn.tablebind.component.input.write.tip[col.type]($field, col.tip);
                $.fn.tablebind.component.input.write.values(col.type, $field, col.options, col.optionValues);
                if(col.required === true) $field.addClass('required');
                if($.fn.tablebind.component.input.bind[col.type] === undefined);
                else {
                    $.fn.tablebind.component.input.bind[col.type]($field, col.ref);
                }
                //
                $form.append($field);
            });

            $form.append($actions);

            $form.append('<div class="ui error message"></div>');

            $view.append($content);
            $view.append($form_footer);

            module.get.onEditHide = function () {
                messageClear($form_footer);
                messageHide($form_footer);
            }

            $actions.children('.button').eq(0).click(function () {
                messageClear($form_footer);
                messageHide($form_footer);
                $view.modal('hide');
            });
            $actions.children('.button').eq(1).click(function () {
                $form.find('.ui.error.message').html('');
                messageInfo($form_footer)
                if(settings.updateUrl === '') {
                    return;
                }
                disableForm($form);
                setTimeout(function () {
                    $form.form('validate form')
                }, 500);
            });

            //form validate rules
            var fields = {},fieldIds = [],fieldCols={};
            $.each(columns, function (idx, col) {
                if (!col.updatable) return true;
                fields[col.name] = {
                    identifier : col.name,
                    rules : col.validate
                }
                fieldIds.push(col.name);
                fieldCols[col.name] = col;
            });

            $form.form({
                fields : fields,
                onSuccess : function (event, fields) {
                    $.each(fieldIds, function (idx, name) {
                        var col = fieldCols[name];
                        var fieldValue = fields[name];
                        if(!(fieldValue === '') || !(fieldValue.trim() === '')) return true;
                        if(((col.type === 'image') || (col.type === 'file') || (col.type === 'reference'))) {
                            delete fields[name];
                        } else if((col.emptyIsNull === true)) {
                            delete fields[name];
                        }
                    });
                    var headers = module.get.tokens();
                    var id = $form.children('input[data-name=id]').val(),
                        suc = false;
                    fields[settings.key] = id;
                    //post data
                    $.ajax({
                        type : 'POST',
                        url : settings.updateUrl,
                        data : JSON.stringify(fields),
                        contentType : "application/json",
                        dataType : 'json',
                        headers : headers,
                        success: function (data){
                            if(data.code === 1) {
                                $.each(data.data, function (id, error) {
                                    $form.form('add prompt', id);
                                    console.log(error);
                                });
                                $form.form('add errors', data.data);
                            } else {
                                messageSuccess($form_footer);
                                suc = true;
                                settings.onModSuccess($view, $wrapper, table_id);
                                setTimeout(function () {
                                    enableForm($form);
                                    $view.modal('hide');
                                    retriveTable();
                                    //location.reload();
                                }, 500);
                            }
                        }
                    }).done(function (data) {
                    }).fail(function (data) {
                        console.info('fail');
                        messageFail($form_footer, JSON.stringify(data), $view);
                        settings.onModFail(data, $view, $wrapper, table_id);
                    }).always(function () {
                        if($form_footer.hasClass('info')) {
                            messageHide($form_footer);
                        }
                        if(!suc)enableForm($form);
                    });
                },
                onFailure : function (formErrors, fields) {
                    messageHide($form_footer)
                    enableForm($form);
                }

            });

            return $view;
        }

        function importData (file) {
            module.get.loader.process().dimmer('show');

            var headers = module.get.tokens();

            $.ajax({
                type : 'POST',
                url : settings.importUrl,
                cache: false,
                data : file,
                processData: false,
                contentType: false,
                //contentType : "application/json",
                //dataType : 'json',
                headers : headers,
                success: function (data){
                    if(data.code === 1) {
                        var err = '';
                        $.each(data.data, function (id, error) {
                            console.log(id+':'+error);
                            err += (id+':'+error+'; ')
                        });
                        module.get.loader.fail('请求错误！', JSON.stringify(data)).dimmer('show');
                    } else {
                        module.get.loader.success().dimmer('show');
                        setTimeout(function () {
                            module.get.loader.success().dimmer('hide');
                            retriveTable();
                        }, 300);
                    }
                }
            }).fail(function (data) {
                module.get.loader.fail('操作失败！', JSON.stringify(data)).dimmer('show');
                console.info('fail');
            });
        }

        function createDeleteView() {

            var $view = $('<div class="ui basic modal small"></div>'),
                $header = $('<div class="ui icon header"><i class="warning circle icon red"></i>正在进行危险操作...</div>'),
                $content = $('<div class="content"><i class="info circle icon"></i>确定<span class="red">删除数据</span>?</div>'),
                $hide_key = $('<input type="hidden" data-name="id">'),
                $actions = $('<div class="actions">' +
                    '<div class="ui red ok inverted button"><i class="checkmark icon"></i>是</div>' +
                    '<div class="ui green basic cancel inverted button"><i class="remove icon"></i>否</div>' +
                    '</div>');
            $view.attr('data-section', 'delete');
            $view.attr('data-table', table_id);

            $view.html($header);
            $content.append($hide_key);
            $view.append($content);
            $view.append($actions);
            $actions.children('.cancel').click(function () {
                $view.modal('hide');
            });
            $actions.children('.ok').click(function () {
                $view.modal('hide');
                module.get.loader.process('数据删除中...').dimmer('show');

                var id = $content.children('input').val(),
                    post_body = {id:id};

                var headers = module.get.tokens();
                $.ajax({
                    type : 'POST',
                    url : settings.deleteUrl,
                    data : JSON.stringify(post_body),
                    contentType : "application/json",
                    dataType : 'json',
                    headers : headers,
                    success: function (data){
                        if(data.code === 1) {
                            var err = '';
                            $.each(data.data, function (id, error) {
                                console.log(id+':'+error);
                                err += (id+':'+error+'; ')
                            });
                            module.get.loader.fail('请求错误！', JSON.stringify(data)).dimmer('show');
                        } else {
                            module.get.loader.success().dimmer('show');

                            settings.onDelSuccess($view, $wrapper, table_id);

                            setTimeout(function () {
                                module.get.loader.success().dimmer('hide');
                                retriveTable();
                                //location.reload();
                            }, 300);

                        }
                    }
                }).fail(function (data) {
                    module.get.loader.fail('操作失败！', JSON.stringify(data)).dimmer('show');
                    console.info('fail');
                });

            });

            return $view;
        }

        function createCommonOpView() {
            var $view = $('<div class="ui small modal"></div>'),
            $close = $('<i class="close icon"></i>'),
            $header = $('<div class="header"></div>'),
            $content = $('<div class="content"></div>'),
            $actions = $('<div class="actions">' +
                '<div class="ui negative button">否</div>' +
                '<div class="ui positive button">是</div>' +
                '</div>');
            $view.append($close);
            $view.append($header);
            $view.append($content);
            $view.append($actions);

            $actions.children('div.negative').click(function () {
                $view.modal('hide');
                $view.remove();
            });

            return $view;

        }
        function retriveTable() {
            module.get.loader.process('数据加载中...').dimmer('show');

            var headers = module.get.tokens();
            var result = {status:'fail',data:{}};
            var queryData = (arguments.length > 0)
                ? arguments[0]
                : module.get.query(),
                callback = (arguments.length > 1)
                    ? arguments[1]
                    : module.refresh;
            $.ajax({
                //async : false,
                type : 'GET',
                url : settings.dataUrl,
                data : queryData,
                dataType : 'json',
                headers : headers,
                success: function (data){
                    if(data.code === 1) {
                        $.each(data.data, function (id, error) {
                            console.log(id+':'+error);
                            module.get.loader.fail('请求错误', JSON.stringify(data)).dimmer('show');
                        });
                    } else {
                        result.status='success';
                        result.data = data.data;
                        callback(result.data);
                    }
                }
            }).done(function (data) {
                module.get.loader.process('数据加载中...').dimmer('hide');
            }).fail(function (data) {
                console.info('fail');
                result.data = data;
                module.get.loader.fail('操作失败', JSON.stringify(data)).dimmer('show');
            });

            return result;
        }

        module.initialize();

        return this;
    };

    $.fn.tablebind.settings = {
        key : "id",
        tableId : undefined,
        dbClickEditable : false,
        table : 'table',
        erorrClass : '',
        editorClass : '',
        changeClass : '',
        enableAdd : true,
        enableImport : false,
        importTemplateUrl : '',
        importUrl : '',
        enableEdit : true,
        enableDelete : true,
        autoLoad : false,
        dataUrl : '',
        addUrl : '',
        updateUrl : '',
        deleteUrl : '',
        customOpItems : [],
        onModSuccess : function ($view, $wrapper, id) {
            //default refresh table
            //modal hide
        },
        onModFail : function (error, $view, $wrapper, id) {

        },
        onAddSucess : function ($view, $wrapper, id) {
            //default refresh table
            //toggle form
        },
        //
        onAddFail : function ($view, $wrapper, id) {
            //show fail cause reason
        },
        onDelSuccess : function ($view, $wrapper, id) {
            //default refresh table
            //modal hide
        },
        onDelFail : function (error, $view, $wrapper, id) {
        },
        lengthList : [20, 30, 50, 100]
    };

    $.fn.tablebind.component = {
        output : {
            write : {
                text : function (val) {
                    return val;
                },
                password : function (val) {
                    return val;
                },
                image : function (val) {
                    return '<img class="ui mini rounded image" src="'+val+'"/>';
                },
                date : function (val) {
                    return val;
                },
                datetime : function (val) {
                    return val;
                },
                time : function (val) {
                    return val;
                },
                checkbox : function (val) {
                    var _checkbox = val;
                    if((val === true)||(val === 'on')) {
                        _checkbox = '<img data-value="on" src="/static/img/checkbox_checked.gif"/>';
                    } else {
                        _checkbox = '<img data-value="off" src="/static/img/checkbox_unchecked.gif"/>';
                    }
                    return _checkbox;
                },
                select : function (val, ops, values) {
                    return functions.value2option(val, ops, values);
                },
                number : function (val) {
                },
                email : function (val) {
                },
                textarea : function (val) {
                    return val;
                },
                file : function (val) {
                    return '<a href="'+val+'">文件</a>';
                },
                currency : function (val) {
                    return val;
                },
                reference : function (val, val_label) {
                    var $label = $('<input type="hidden">'),
                    $f = $('<div></div>'),
                    r_c = '';
                    $f.text(val_label);
                    $label.val(val);
                    r_c = $f.text() + $label[0].outerHTML;
                    return r_c;
                },
                images : function (val) {
                    if(val === undefined) return '<div class="ui mini images"></div>';
                    var imgs = val.split(',');
                    var out = $('<div><div class="ui mini images"></div>');

                    $.each(imgs, function (idx, src) {
                        var link = $('<a class="ui mini image">');
                        var img = $('<img class="ui mini rounded image">');
                        link.attr('href', src);
                        link.attr('target', 'blank');
                        img.attr('src', src);
                        //
                        functions.loadImage(src, function (dataURL) {
                           img.attr('data-src', dataURL);
                        });

                        link.append(img);
                        out.children('div.ui.images').append(link);
                    });
                    //
                    return out.html();
                }
            },
            retrieve : {
                text : function ($output) {
                    return $output.text();
                },
                password : function ($output) {
                    return $output.text();
                },
                image : function ($output) {
                    return $output.find('img').attr('src');
                },
                date : function ($output) {
                    return $output.text();
                },
                datetime : function ($output) {
                    return $output.text();
                },
                time : function ($output) {
                    return $output.text();
                },
                checkbox : function ($output) {
                    var val = $output.find('img').data('value');
                    return (val === 'on')?true:false;
                },
                select : function ($output, ops, values) {
                    return functions.option2value($output.text(), ops, values);
                },
                number : function ($output) {
                    //return $output.text();
                },
                email : function ($output) {
                    //return $output.text();
                },
                textarea : function ($output) {
                    return $output.text();
                },
                file : function ($output) {
                    return $output.find('a').attr('href');
                },
                currency : function ($output) {
                    return $output.text();
                },
                reference : function ($output) {
                    var dat = {};
                    dat.label = $output.text();
                    dat.id = $output.children('input[type=hidden]').val();
                    return dat;
                },
                images : function ($output) {
                    var $imgs = $output.find('div.ui.images a.ui.image');
                    var images = [];
                    $.each($imgs, function (idx, img) {
                        var imageItem = {};
                        imageItem.src = $(img).children('img').attr('src');
                        imageItem.dat = $(img).children('img').attr('src');
                        //imageItem.dat = $(img).children('img').data('src');
                        images.push(imageItem);
                    });

                    return images;
                }
            }

        },
        input : {
            write : {
                inline : {
                    text : '<div class=" field"></div>',
                    password : '<div class=" field"></div>',
                    image : '<div class=" field"></div>',
                    date : '<div class="ui calendar  field"></div>',
                    datetime : '<div class="ui calendar  field"></div>',
                    time : '<div class="ui calendar  field"></div>',
                    checkbox : '<div class=" field"></div>',
                    select : '<div class=" field"></div>',
                    textarea : '<div class=" field"></div>',
                    file : '<div class=" field"></div>',
                    currency : '<div class=" field"></div>',
                    reference : '<div class=" field"></div>',
                    images : '<div class=" field"></div>'

                },
                input : {
                    text : '<input type="text">',
                    password : '<input type="password">',
                    image : '<input type="file" style="display: none;"><input type="hidden"><img class="ui avatar image" src=""><div class="ui icon button"><i class="upload icon"></i></div>',
                    date : '<div class="ui input left icon"><i class="calendar icon"></i><input type="text"></div>',
                    datetime : '<div class="ui input left icon"><i class="calendar icon"></i><input type="text"></div>',
                    time : '<div class="ui input left icon"><i class="calendar icon"></i><input type="text"></div>',
                    checkbox : '<div class="ui checkbox"><input type="checkbox"><label></label></div>',
                    select : '<select class="ui dropdown"><option value="">--无--</option></select>',
                    number : '',
                    email : '',
                    textarea : '<textarea rows="4"></textarea>',
                    file : '<input type="file" style="display: none;"><input type="hidden"><div class="ui large label"></div><div class="ui icon button"><i class="upload icon"></i></div>',
                    currency : '<div class="ui input left icon"><i class="yen icon"></i><input type="text"></div>',
                    reference : '<div class="ui icon input"><input type="text" data-type="label"><i class="green circular search link icon"></i><input type="hidden" data-type="id"></div>',
                    images : '<div>' +
                                '<div class="ui buttons">' +
                                    '<div class="ui button">移除</div>' +
                                    '<div class="or" data-text="or"></div>' +
                                    '<div class="ui positive button">添加</div>' +
                                '</div>' +
                                '<span class="drag area">将图片拖到此处</span>' +
                                '<div class="ui medium images preview">' +
                             '</div>' +
                            '<input style="display: none;" type="file" multiple="multiple" accept="image/*">' +
                            '<input type="hidden">'
                },
                values : function (type, $field, ops, values) {
                    var select = function ($field, ops, values) {
                        var select = '';
                        ops = $.isArray(ops) ? ops : [];
                        values = $.isArray(values) ? values : [];
                        $.each(ops, function (idx, op) {
                            select += '<option value="'+((values[idx]===undefined)?(''):(values[idx]))+'">'+op+'</option>';
                        })
                        $field.find('select').append(select);
                    }
                    if(type === 'select') {
                        select($field, ops, values);
                    }
                },
                tip : {
                    text : function ($field, tip) {
                        $field.find('input').attr('placeholder', tip);
                    },
                    password : function ($field, tip) {
                        $field.find('input').attr('placeholder', tip);
                    },
                    image : function ($field, tip) {
                    },
                    images : function ($field, tip) {
                    },
                    date : function ($field, tip) {
                        $field.find('input').attr('placeholder', tip);
                    },
                    datetime : function ($field, tip) {
                        $field.find('input').attr('placeholder', tip);
                    },
                    time : function ($field, tip) {
                        $field.find('input').attr('placeholder', tip);
                    },
                    checkbox : function ($field, tip) {
                    },
                    select : function ($field, tip) {
                    },
                    textarea : function ($field, tip) {
                        $field.find('textarea').attr('placeholder', tip);
                    },
                    file : function ($field, tip) {
                    },
                    currency : function ($field, tip) {
                        $field.find('input').attr('placeholder', tip);
                    },
                    reference : function ($field, tip) {
                        $field.find('input[data-type=label]').attr('placeholder', tip);
                    }
                },
                name : {
                    text : function ($field, name) {
                        $field.find('input').attr('name', name);
                    },
                    password : function ($field, name) {
                        $field.find('input').attr('name', name);
                    },
                    image : function ($field, name) {
                        $field.find('input[type=hidden]').attr('name', name);
                        $field.find('img').attr('data-name', name);
                    },
                    images : function ($field, name) {
                        $field.find('input[type=hidden]').attr('name', name);
                    },
                    date : function ($field, name) {
                        $field.find('input').attr('name', name);
                    },
                    datetime : function ($field, name) {
                        $field.find('input').attr('name', name);
                    },
                    time : function ($field, name) {
                        $field.find('input').attr('name', name);
                    },
                    checkbox : function ($field, name) {
                        $field.find('input').attr('name', name);
                    },
                    select : function ($field, name) {
                        $field.find('select').attr('name', name);
                    },
                    textarea : function ($field, name) {
                        $field.find('textarea').attr('name', name);
                    },
                    file : function ($field, name) {
                        $field.find('input[type=hidden]').attr('name', name);
                    },
                    currency : function ($field, name) {
                        $field.find('input').attr('name', name);
                    },
                    reference : function ($field, name) {
                        $field.find('input[data-type=id]').attr('name', name);
                    }
                },
                label : {
                    text : function () {
                        var label_text = arguments.length > 0 ? arguments[0] : '';
                        return '<label>'+label_text+'</label>';
                    }
                },
                val : {
                    text : function ($field, value) {
                        $field.find('input').val(value);
                    },
                    password : function ($field, value) {
                        $field.find('input').val(value);
                    },
                    image : function ($field, value) {
                        $field.find('input[type=hidden]').val('');
                        $field.find('img').attr('src', value);
                    },
                    date : function ($field, value) {
                        $field.find('input').val(value);
                    },
                    datetime : function ($field, value) {
                        $field.find('input').val(value);
                    },
                    time : function ($field, value) {
                        $field.find('input').val(value);
                    },
                    checkbox : function ($field, value) {
                        $field.find('input').attr("checked",((value === true)?true:false));
                    },
                    select : function ($field, value) {
                        $field.find('select').dropdown('set selected', value);
                    },
                    textarea : function ($field, value) {
                        $field.find('textarea').val(value);
                    },
                    file : function ($field, value) {
                        $field.find('input[type=hidden]').val('');
                        $field.find('.label').text(value);
                    },
                    currency : function ($field, value) {
                        $field.find('input').val(value);
                    },
                    reference : function ($field, value) {
                        $field.find('input[data-type=label]').val(value.label);
                        $field.find('input[data-type=id]').val(value.id);
                    },
                    images : function ($field, value) {
                        var $preview = $field.find('.ui.images.preview');
                        var images = [];
                        $.each(value, function (idx, image) {
                            var img_div = $('<div class="ui image"></div>');
                            var img = $('<img>')
                            img.attr('src', image.src);
                            images.push(image.dat);
                            img_div.append(img);
                            img_div.click(function () {
                                $(this).toggleClass('selected');
                            });
                            $preview.append(img_div);
                        });
                        $field.find('input[type=hidden]').val(JSON.stringify(images));
                    }
                },
                reset : {
                    text : function ($field) {
                        $field.find('input').val('');
                    },
                    password : function ($field) {
                        $field.find('input').val('');
                    },
                    image : function ($field) {
                        $field.find('input[type=hidden]').val('');
                        $field.find('img').attr('src', '');
                    },
                    images : function ($field) {
                        $field.find('input[type=hidden]').val('');
                        $field.find('.ui.images.preview').html('');
                    },
                    date : function ($field) {
                        $field.find('input').val('');
                    },
                    datetime : function ($field) {
                        $field.find('input').val('');
                    },
                    time : function ($field) {
                        $field.find('input').val('');
                    },
                    checkbox : function ($field) {
                        $field.find('input').attr("checked",false);
                    },
                    select : function ($field) {
                        $field.find('select').dropdown('clear');
                    },
                    textarea : function ($field) {
                        $field.find('textarea').val('');
                    },
                    file : function ($field) {
                        $field.find('input[type=hidden]').val('');
                        $field.find('.label').text('');
                    },
                    currency : function ($field) {
                        $field.find('input').val('');
                    },
                    reference : function ($field) {
                        $field.find('input').val('');
                    }
                }
            },
            read : {
                input : {
                    text : function ($field) {
                        return $field.find('input');
                    },
                    password : function ($field) {
                        return $field.find('input');
                    },
                    image : function ($field) {
                        return $field.find('input[type=hidden]');
                    },
                    images : function ($field) {
                        return $field.find('input[type=hidden]');
                    },
                    date : function ($field) {
                        return $field.find('input');
                    },
                    datetime : function ($field) {
                        return $field.find('input');
                    },
                    time : function ($field) {
                        return $field.find('input');
                    },
                    checkbox : function ($field) {
                        return $field.find('input');
                    },
                    select : function ($field) {
                        return $field.find('select');
                    },
                    textarea : function ($field) {
                        return $field.find('textarea');
                    },
                    file : function ($field) {
                        return $field.find('input[type=hidden]');
                    },
                    currency : function ($field) {
                        return $field.find('input');
                    },
                    reference : function ($field) {
                        return $field.find('input[data-type=id]');
                    }
                },
                name : {
                    text : function ($field) {
                        return $field.find('input').attr('name');
                    },
                    password : function ($field) {
                        return $field.find('input');
                    },
                    image : function ($field) {
                        return $field.find('input[type=hidden]').attr('name');
                    },
                    images : function ($field) {
                        return $field.find('input[type=hidden]').attr('name');
                    },
                    date : function ($field) {
                        return $field.find('input').attr('name');
                    },
                    datetime : function ($field) {
                        return $field.find('input').attr('name');
                    },
                    time : function ($field) {
                        return $field.find('input').attr('name');
                    },
                    checkbox : function ($field) {
                        return $field.find('input').attr('name');
                    },
                    select : function ($field) {
                        return $field.find('select').attr('name');
                    },
                    textarea : function ($field) {
                        return $field.find('textarea').attr('name');
                    },
                    file : function ($field) {
                        return $field.find('input[type=hidden]').attr('name');
                    },
                    currency : function ($field) {
                        return $field.find('input').attr('name');
                    },
                    reference : function ($field) {
                        return $field.find('input[data-type=id]').attr('name');
                    }
                }
            },
            bind : {
                image : function () {
                    var $ele = arguments.length > 0 ? $(arguments[0]) : $('');
                    $ele.find('div.ui.icon.button').click(function () {
                        $ele.children('input[type=file]').click();
                    });
                    $ele.children('input[type=file]').on('change', function (e) {
                        if(e.target.files && e.target.files[0]) {
                            var file = e.target.files[0];
                            //set img
                            $ele.find('img').attr('src', functions.readFileUrl(file));
                            var input = $ele.find('input[type=hidden]');
                            functions.readFileData(file, input);
                        }
                    });
                },
                file : function () {
                    var $ele = arguments.length > 0 ? $(arguments[0]) : $('');
                    $ele.find('div.ui.icon.button').click(function () {
                        $ele.children('input[type=file]').click();
                    });
                    $ele.children('input[type=file]').on('change', function (e) {
                        if(e.target.files && e.target.files[0]) {
                            var file = e.target.files[0];
                            $ele.find('div.ui.label').text(file.name);//file.size file.type
                            var input = $ele.find('input[type=hidden]');
                            functions.readFileData(file, input);
                        }
                    });
                },
                reference : function () {
                    var $ele = arguments.length > 0 ? $(arguments[0]) : $(''),
                    set = arguments.length > 1 ? (arguments[1]) : undefined;
                    if(set === undefined) return;
                    var rand = Math.random(),
                        url = set.url,
                        key = set.key,
                        cols = set.cols,
                        params = {};
                    params.key = key;
                    //params.label ??
                    params.cols = cols;

                    var params_str = JSON.stringify(params);
                    params_str = encodeURI(params_str);

                    $ele.find('i.search.link.icon').click(function () {
                        //
                        $ele.attr('data-ref-ran', rand);
                        var o_url = "/loaddata/list";
                        o_url += "?";
                        o_url += "url="+url;
                        o_url += "&";
                        o_url += "params="+params_str;
                        o_url += "&";
                        o_url += "r="+rand;
                        window.open(o_url, 'popup','height=540,width=670,resizable=yes,scrollbars=yes,toolbar=no,status=no');
                    });

                    $ele.find('input[data-type=label]').on('dbclick', function () {
                        $ele.find('i.search.link.icon').click();
                    });
                    $ele.find('input[data-type=label]').on('input propertychange', function () {
                        if($(this).val().length === 0) {
                            $ele.find('input[data-type=id]').val('');
                        }
                    });
                },
                images : function () {
                    var $ele = arguments.length > 0 ? $(arguments[0]) : $('');
                    var $multiInput = $ele.find('input[type=file][multiple=multiple]');
                    var input = $ele.find('input[type=hidden]');
                    var preview = $ele.find('.ui.images.preview');
                    var drag_area = $ele.find('.drag.area');

                    var addBtn = $ele.find('.ui.buttons .ui.button').eq(1);
                    var delBtn = $ele.find('.ui.buttons .ui.button').eq(0);
                    //add button event
                    addBtn.click(function () {
                        $multiInput.click();
                    });
                    //remove button event
                    delBtn.click(function () {
                        var idxs = [];
                        preview.find('.ui.image').each(function (idx, img) {
                            if($(this).hasClass('selected')) {
                                $(this).remove();
                                idxs.push(idx);
                            }
                        });
                        functions.removeImage(idxs, input);
                    });
                    //multiple input event
                    $multiInput.on('change', function (e) {
                        var files = e.target.files;
                        functions.handImages(files, input, preview);
                    });
                    //drag zone event
                    //focus
                    drag_area.on('dragover', function (e) {
                        functions.preventEvent(e);
                    });
                    //blur
                    drag_area.on('dragleave', function (e) {
                        functions.preventEvent(e);
                    });
                    //active
                    drag_area.on('drop', function (e) {
                        functions.preventEvent(e);
                        var files = e.originalEvent.dataTransfer.files;
                        functions.handImages(files, input, preview);
                    });

                }
            }
        },

        validate : {

        }
    };

    $.fn.tablebind.columns = [
        {
            label : '#',
            name : 'rowno',
            writable : false,
            updatable : false,
            enableValidate : false,
        }
    ];

    $.fn.tablebind.column = {
        index : 0,
        label : '',
        type : 'text',
        options : [],
        optionValues : [],
        name : '',
        textName : '',
        emptyIsNull : false,
        tip : '',
        required : false,
        writable : true,
        updatable : true,
        searchable : false,
        enableValidate : true,
        validate: [],
        ref : {
            url : '',
            key : '',
            label : '',
            cols : [
                {
                    name : '',
                    label : ''
                }
            ]
        }
    };

    $.fn.tablebind.columnOpItem = {
        ui:'<div class="ui button">item</div>',
        url:'',
        data:[],
        extraData:{},
        method:'POST',
        confirmEnable:true,
        confirmHeader:'操作提示',
        confirmText:'是否确认提交操作？'
    };
    var functions = {
        loadImage : function (url, callback) {
            var img = new Image();
            img.setAttribute('crossOrigin', 'anonymous');
            img.src = url;
            var canvas = document.createElement("canvas"),
                canvasContext = canvas.getContext("2d");

            img.onload = function () {
                //Set canvas size is same as the picture
                canvas.width = img.width;
                canvas.height = img.height;
                // draw image into canvas element
                canvasContext.drawImage(img, 0, 0, img.width, img.height);
                // get canvas contents as a data URL (returns png format by default)
                var dataURL = canvas.toDataURL();
                //execute callback functions
                callback(dataURL);
            }
        },
        isSupportFile : function() {
            if (window.File && window.FileReader && window.FileList && window.Blob) {
                return true;
            }
            return false;
        },
        readFileData : function(file, $e) {
            if(!functions.isSupportFile()) return '';
            var reader = new FileReader(),
                dataURL = '';
            if(!(file instanceof window.File)) {
                return dataURL;
            }
            reader.readAsDataURL(file);
            reader.onload = function (e) {
                var dataSRC = e.target.result,
                    data = dataSRC.replace(/^data:\w+\/\w+;base64,/, '');
                dataURL = data;
                $e.val(dataURL);
            }
        },
        readFileUrl : function (file) {
            var file_url = '';
            if(file instanceof window.File) {
                file_url = URL.createObjectURL(file);
            }
            return file_url;
        },
        option2value : function (op, ops, values) {
            var value = '';
            ops = $.isArray(ops)?ops:[];
            values = $.isArray(values)?values:[];
            $.each(ops, function (idx,_op) {
                if(_op === op) {
                    value = values[idx];
                    return false;
                }
            });
            value = (value === undefined) ? '' : value;
            return value;
        },
        value2option : function (value, ops, values) {
            var op = '';
            ops = $.isArray(ops)?ops:[];
            values = $.isArray(values)?values:[];
            $.each(values, function (idx,_value) {
                if(_value === value) {
                    op = ops[idx];
                    return false;
                }
            });
            op = (op === undefined) ? '' : op;
            return op;
        },
        preventEvent : function (e) {
            e.stopPropagation();
            e.preventDefault();
        },
        handImages : function (images, input, preview) {
            $.each(images, function (idx, image) {
                if(image.type.indexOf('image') === 0) {

                    var reader = new FileReader();
                    reader.onload =  function(e) {
                        var result = e.target.result;
                        result = result.replace(/^data:\w+\/\w+;base64,/, '');
                        functions.pushImages(result, input);
                        var img_div = $('<div class="ui image"><img></div>'),
                            img = img_div.children('img');
                        img_div.click(function () {
                            $(this).toggleClass('selected');
                        });
                        img.attr('src', URL.createObjectURL(image));
                        img.attr('title', image.name);
                        preview.append(img_div);
                    };
                    reader.readAsDataURL(image);
                } else {
                }
            });
        },
        parseImagesData : function (input) {
            var imagesData = input.val();
            try {
                imagesData = JSON.parse(imagesData);
            } catch (err) {
                imagesData = [];
            }
            if(!$.isArray(imagesData)) {
                imagesData = [];
            }

            return imagesData;
        },
        pushImages : function (imageData, input) {
            var imagesData = functions.parseImagesData(input);
            imagesData.push(imageData);
            input.val(JSON.stringify(imagesData));
        },
        removeImage : function (images, input) {
            var imagesData = functions.parseImagesData(input);
            if($.isArray(images)) {
                $.each(images, function (idx, image) {
                    image = image - idx;
                    imagesData.splice(image, 1);
                });
            }
            input.val(JSON.stringify(imagesData));
        }
    };

})(jQuery, window, document);